using System;
using System.Collections.Generic;
using Net.Common;
using PEMath;
using PEPhysx;
using UnityEngine;

/****************************************************
// 功能：战斗管理器
// | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
// | Copyright (c) 2021-2025 聊来 All rights reserved.
// | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">聊来</a> )
// | @Author: 贯彻己道的云 <18970881148@qq.com>
// | DateTime: 2025/3/27 17:31:40
*****************************************************/

public class BattleManager : MonoBehaviour
{
    private MapRoot mapRoot;
    private EnvColliders logicEnv;

    private Transform transFollow;

    // 英雄角色集合
    private readonly List<Hero> heroList = new List<Hero>();
    private readonly List<Bullet> bulletList = new List<Bullet>();
    private readonly List<Tower> towerList = new List<Tower>();
    private readonly List<Soldier> soldierList = new List<Soldier>();
    private readonly List<LogicTimer> timerList = new List<LogicTimer>();
    
    private int waveIndex = 0;
    private int income = 0;

    public void init(List<BattleHero> battleHeroList, MapConfig mapConfig)
    {
        //初始化碰撞环境
        InitEnv();

        // 英雄
        InitHero(battleHeroList, mapConfig);
        
        // 防御塔
        InitTower(mapConfig);
        
        
        // 小兵
        ++waveIndex;

        // 延迟创建小兵
        void CreateSoldier()
        {
            CreateSoldierBatch(mapConfig, TeamEnum.Blue);
            CreateSoldierBatch(mapConfig, TeamEnum.Red);
        }
        var pt = new LogicTimer(CreateSoldier, mapConfig.bornDelay, mapConfig.waveInterval);
        timerList.Add(pt);
        
        // 金币 没有多大作用
        InitIncome();
    }
    
    public void UnInit()
    {
        heroList.Clear();
        bulletList.Clear();
        towerList.Clear();
        soldierList.Clear();
        CalcRule.blueTeamSoldier.Clear();
        CalcRule.redTeamSoldier.Clear();
    }

    /// <summary>
    /// 初始化碰撞环境
    /// </summary>
    private void InitEnv()
    {
        var transMapRoot = GameObject.FindGameObjectWithTag(Constants.MAP_ROOT).transform;
        mapRoot = transMapRoot.GetComponent<MapRoot>();
        var envColliderList = GenerateEnvCollider(mapRoot.transEnvCollider);
        logicEnv = new EnvColliders {
            envColliCfgLst = envColliderList
        };
        logicEnv.Init();
    }

    private void InitHero(List<BattleHero> battleHeroList, MapConfig mapConfig)
    {
        var num = battleHeroList.Count / 2;

        var blueTeamHero = new Hero[num];
        var redTeamHero = new Hero[num];
        for (var i = 0; i < battleHeroList.Count; i++)
        {
            HeroData hd = new HeroData()
            {
                heroId = battleHeroList[i].heroId,
                posIndex = i,
                userName = battleHeroList[i].userName,
                unitConfig = ResourceManager.Instance.GetUnitConfigData(battleHeroList[i].heroId)
            };
            

            Hero hero;
            if (i < num)
            {
                hd.teamEnum = TeamEnum.Blue;
                hd.bornPos = mapConfig.blueBorn + new PEVector3(0,0, i * (PEInt)1.5f);
                hero = new Hero(hd);
                blueTeamHero[i] = hero;
            }
            else
            {
                hd.teamEnum = TeamEnum.Red;
                hd.bornPos = mapConfig.redBorn + new PEVector3(0,0, (i - num) * (PEInt)1.5f);
                hero = new Hero(hd);
                redTeamHero[i - num] = hero;
            }
            
            hero.LogicInit();
            heroList.Add(hero);
        }

        CalcRule.blueTeamHero = blueTeamHero;
        CalcRule.redTeamHero = redTeamHero;
    }


    private void InitTower(MapConfig mapConfig)
    {
        var num = mapConfig.towerIdArr.Length / 2;

        var blueTeamTower = new Tower[num];
        var redTeamTower = new Tower[num];
        for (var i = 0; i < mapConfig.towerIdArr.Length; i++)
        {
            var td = new TowerData()
            {
                towerId = mapConfig.towerIdArr[i],
                towerIndex = i,
                unitConfig = ResourceManager.Instance.GetUnitConfigData(mapConfig.towerIdArr[i])
            };
            

            Tower tower;
            if (i < num)
            {
                td.teamEnum = TeamEnum.Blue;
                td.bornPos = mapConfig.towerPosArr[i];
                tower = new Tower(td);
                blueTeamTower[i] = tower;
            }
            else
            {
                td.teamEnum = TeamEnum.Red;
                td.bornPos = mapConfig.towerPosArr[i];
                tower = new Tower(td);
                redTeamTower[i - num] = tower;
            }
            
            tower.LogicInit();
            towerList.Add(tower);
        }

        CalcRule.blueTeamTower = blueTeamTower;
        CalcRule.redTeamTower = redTeamTower;
    }


    private void CreateSoldierBatch(MapConfig mapConfig, TeamEnum team)
    {
        int[] idArr;
        PEVector3[] posArr;
        if (team == TeamEnum.Blue)
        {
            idArr = mapConfig.blueSoldierIdArr;
            posArr = mapConfig.blueSoldierPosArr;
        }
        else
        {
            idArr = mapConfig.redSoldierIdArr;
            posArr = mapConfig.redSoldierPosArr; 
        }

        for (int i = 0; i < idArr.Length; i++)
        {
            SoldierData sd = new SoldierData()
            {
                soldierId = idArr[i],
                waveIndex = waveIndex,
                orderIndex = i,
                soldierName = "soldier_" + idArr[i],
                teamEnum = team,
                bornPos = posArr[i],
                unitConfig = ResourceManager.Instance.GetUnitConfigData(idArr[i])
            };

            LogicTimer pt = new LogicTimer(() =>
            {
                Soldier soldier = new Soldier(sd);
                soldier.LogicInit();
                if (sd.teamEnum == TeamEnum.Blue)
                {
                    CalcRule.blueTeamSoldier.Add(soldier);
                }
                else
                {
                    CalcRule.redTeamSoldier.Add(soldier); 
                }
                soldierList.Add(soldier);
            }, (i/2) * mapConfig.bornInterval);
            timerList.Add(pt);
        }
    }
    
    
    private void InitIncome() {
        var pt = new LogicTimer(() => {
            ++income;
            BattleController.Instance.RefreshIncome(income);
        }, 0, 2000);
        timerList.Add(pt);
    }
    
    private List<ColliderConfig> GenerateEnvCollider(Transform transRoot)
    {
        List<ColliderConfig> envColliCfgLst = new List<ColliderConfig>();
        BoxCollider[] boxArr = transRoot.GetComponentsInChildren<BoxCollider>();
        for(int i = 0; i < boxArr.Length; i++) {
            Transform trans = boxArr[i].transform;
            var cfg = new ColliderConfig {
                mPos = new PEVector3(trans.position)
            };
            cfg.mSize = new PEVector3(trans.localScale / 2);
            cfg.mType = ColliderType.Box;
            cfg.mAxis = new PEVector3[3];
            cfg.mAxis[0] = new PEVector3(trans.right);
            cfg.mAxis[1] = new PEVector3(trans.up);
            cfg.mAxis[2] = new PEVector3(trans.forward);

            envColliCfgLst.Add(cfg);
        }

        CapsuleCollider[] cylindderArr = transRoot.GetComponentsInChildren<CapsuleCollider>();
        for(int i = 0; i < cylindderArr.Length; i++) {
            Transform trans = cylindderArr[i].transform;
            var cfg = new ColliderConfig {
                mPos = new PEVector3(trans.position)
            };
            cfg.mType = ColliderType.Cylinder;
            cfg.mRadius = (PEInt)(trans.localScale.x / 2);

            envColliCfgLst.Add(cfg);
        }
        return envColliCfgLst;
    }
    public void Tick()
    {

        for (var i = bulletList.Count - 1; i >= 0; i--)
        {
            if (bulletList[i].unitState == SubUnitState.None)
            {
                bulletList[i].LogicUnInit();
                bulletList.RemoveAt(i);
            }
            else
            {
                bulletList[i].LogicTick();
            }
        }
        
        // hero tick
        foreach (var hero in heroList)
        {
            hero.LogicTick();
        }

        // tower tick
        for (var i = towerList.Count - 1; i >= 0; i--)
        {
            var tower = towerList[i];
            if (tower.unitState != UnitStateEnum.Dead)
            {
                towerList[i].LogicTick();
            }
            else
            {
                towerList[i].LogicUnInit();
                towerList.RemoveAt(i);
            }
            
        }
        
        // soldier tick
        for (var i = soldierList.Count - 1; i >= 0; i--)
        {
            var soldier = soldierList[i];
            if (soldier.unitState != UnitStateEnum.Dead)
            {
                soldierList[i].LogicTick();
            }
            else
            {
                if (soldier.IsTeam(TeamEnum.Blue))
                {
                    var index = CalcRule.blueTeamSoldier.IndexOf(soldier);
                    CalcRule.blueTeamSoldier.RemoveAt(index);
                }
                else
                {
                    var index = CalcRule.redTeamSoldier.IndexOf(soldier);
                    CalcRule.redTeamSoldier.RemoveAt(index);
                }
                soldierList[i].LogicUnInit();
                soldierList.RemoveAt(i);
            }
            
        }
        
        for(var i = timerList.Count - 1; i >= 0; --i) {
            var timer = timerList[i];
            if(timer.IsActive) {
                timer.TickTimer();
            }
            else {
                timerList.RemoveAt(i);
            }
        }
    }

    /// <summary>
    /// 初始化相机跟随
    /// </summary>
    /// <param name="posIndex"></param>
    public void InitFollowTrans(int posIndex)
    {
        transFollow = heroList[posIndex].mainViewUnit.transform;
    }

    public void AddBullet(Bullet bullet) {
        bulletList.Add(bullet);
    }

    public void InputKey(List<OpKey> keyList)
    {
        for(var i = keyList.Count - 1; i >= 0; i--) {
            var key = keyList[i];
            MainLogicUnit hero = heroList[key.opIndex];
            hero.InputKey(key);
        }
    }
    
    
    /// <summary>
    /// 通过逻辑单位获取英雄的表现层单位
    /// </summary>
    /// <param name="posIndex"></param>
    /// <returns></returns>
    public MainLogicUnit GetSelfHero(int posIndex)
    {
        return heroList[posIndex];
    }
    public List<PEColliderBase> GetEnvColliders()
    {
        return logicEnv.GetEnvColliders();
    }

    public bool CancelMove(int posIndex)
    {
        return heroList[posIndex].CancelMove();
    }
    
    public bool IsForbidReleaseSkill(int posIndex) {
        return heroList[posIndex].IsForbidReleaseSkill();
    }

    public bool CancelReleaseSkill(int posIndex, int skillId)
    {
        return heroList[posIndex].CancelReleaseSkill(skillId);
    }
    
    private void Update()
    {
        if (transFollow != null)
        {
            mapRoot.transCameraRoot.position = transFollow.position;
        }
    }
}
